package ace.cmp.jetcache.anno.config;

import com.alicp.jetcache.anno.aop.CacheAdvisor;
import com.alicp.jetcache.anno.aop.JetCacheInterceptor;
import com.alicp.jetcache.anno.config.JetCacheProxyConfiguration;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.annotation.Role;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;

/**
 * @author caspar
 * @date 2023/8/8 10:30 扩展 {@link JetCacheProxyConfiguration} 支持：
 * 1、扫描 Class
 */
@Configuration
public class AceJetCacheProxyConfiguration implements ImportAware, ApplicationContextAware {

  protected AnnotationAttributes enableAceMethodCache;
  private ApplicationContext applicationContext;

  @Override
  public void setImportMetadata(AnnotationMetadata importMetadata) {
    this.enableAceMethodCache =
        AnnotationAttributes.fromMap(
            importMetadata.getAnnotationAttributes(EnableAceMethodCache.class.getName(), false));
    if (this.enableAceMethodCache == null) {
      throw new IllegalArgumentException(
          "@EnableAceMethodCache is not present on importing class "
              + importMetadata.getClassName());
    }
  }

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }

  @Bean(name = CacheAdvisor.CACHE_ADVISOR_BEAN_NAME)
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public CacheAdvisor jetcacheAdvisor(JetCacheInterceptor jetCacheInterceptor) {
    List<String> basePackages =
        Arrays.stream(this.enableAceMethodCache.getStringArray("basePackages"))
            .collect(Collectors.toList());
    Class[] basePackageClasses = this.enableAceMethodCache.getClassArray("basePackageClasses");
    for (Class cls : basePackageClasses) {
      basePackages.add(cls.getPackageName());
    }
    CacheAdvisor advisor = new CacheAdvisor();
    advisor.setAdviceBeanName(CacheAdvisor.CACHE_ADVISOR_BEAN_NAME);
    advisor.setAdvice(jetCacheInterceptor);
    advisor.setBasePackages(basePackages.toArray(new String[basePackages.size()]));
    advisor.setOrder(this.enableAceMethodCache.<Integer>getNumber("order"));
    return advisor;
  }

  @Bean
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public JetCacheInterceptor jetCacheInterceptor() {
    return new JetCacheInterceptor();
  }
}
